package com.xwj.service.Impl;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.xwj.Enums.StatusInfoEnum;
import com.xwj.dao.RaOrderDao;
import com.xwj.dto.OrderInfoDto;
import com.xwj.entity.OrderDetailEntity;
import com.xwj.entity.RaHourseInfo;
import com.xwj.entity.RaOrder;
import com.xwj.service.Interface.RaOrderService;
import lombok.extern.slf4j.Slf4j;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.Future;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.stream.Collectors;

@Slf4j
@Service
@CacheConfig(cacheNames = "RaOrderCache")
public class RaOrderServiceImpl implements RaOrderService {

    @Autowired
    private RaOrderDao raOrderDao;
    @Autowired
    private RaStatusInfoServiceImpl raStatusInfoService;
    @Autowired
    private RaHouseInfoServiceImpl raHouseInfoService;

    private ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();  //读写锁

    private Lock lock = readWriteLock.readLock();

    private String label = StatusInfoEnum.OrderInfo.getName();

    /**
     * 无分页查询
     *
     * @return
     */
    @Override
    @Cacheable(key = "#root.methodName", unless = "#result.size() == 0")
    public List<RaOrder> findAllOrder() {
        try {
            List<RaOrder> raOrderList = raOrderDao.findAllOrder();
            raOrderList.forEach(raOrder -> {
                Map<String, Object> map = new HashMap<>();
                map.put("label", label);
                map.put("type", raOrder.getStatus());
                String status = raStatusInfoService.findOneStatus(map);
                raOrder.setStatusStr(status);
                RaHourseInfo raHourseInfo = raHouseInfoService.findHouseInfoById(raOrder.getHourseId());
                if (raHourseInfo != null)
                    raOrder.setCloudId(raHourseInfo.getCloudId());
            });
            return raOrderList;
        } catch (Exception e) {
            log.error("RaOrderService异常:", e);
            e.printStackTrace();
            return Collections.emptyList();
        }
    }

    /**
     * 无分页条件查询
     *
     * @param orderInfoDto
     * @return
     */
    @Override
    @Cacheable(key = "#root.methodName+'_'+#orderInfoDto.toString()", unless = "#result.size() == 0")
    public List<RaOrder> findOrderByProperty(OrderInfoDto orderInfoDto) {
        try {
            List<RaOrder> raOrderList = raOrderDao.findByProperty(orderInfoDto);
            raOrderList.forEach(raOrder -> {
                Map<String, Object> map = new HashMap<>();
                map.put("label", label);
                map.put("type", raOrder.getStatus());
                String status = raStatusInfoService.findOneStatus(map);
                raOrder.setStatusStr(status);
                RaHourseInfo raHourseInfo = raHouseInfoService.findHouseInfoById(raOrder.getHourseId());
                if (raHourseInfo != null)
                    raOrder.setCloudId(raHourseInfo.getCloudId());
            });
            return raOrderList;
        } catch (Exception e) {
            log.error("RaOrderService异常:", e);
            e.printStackTrace();
            return Collections.emptyList();
        }
    }

    /**
     * 分页查询
     *
     * @param pageIndex
     * @param pageSize
     * @return
     */
    @Override
    @Cacheable(key = "#root.methodName+'_'+#pageIndex", unless = "#result.list.size() == 0")
    public PageInfo<RaOrder> findAllOrderWithPage(int pageIndex, int pageSize) {
        PageHelper.startPage(pageIndex, pageSize);
        lock.lock();
        try {
            List<RaOrder> raOrderList = raOrderDao.findAllOrder();
            raOrderList.forEach(raOrder -> {
                Map<String, Object> map = new HashMap<>();
                map.put("label", label);
                map.put("type", raOrder.getStatus());
                String status = raStatusInfoService.findOneStatus(map);
                raOrder.setStatusStr(status);
                RaHourseInfo raHourseInfo = raHouseInfoService.findHouseInfoById(raOrder.getHourseId());
                if (raHourseInfo != null)
                    raOrder.setCloudId(raHourseInfo.getCloudId());
            });
            PageInfo<RaOrder> pageInfo = new PageInfo<>(raOrderList);
            return pageInfo;
        } catch (Exception e) {
            log.error("RaOrderService异常:", e);
            e.printStackTrace();
            return new PageInfo<>(Collections.emptyList());
        } finally {
            lock.unlock();
        }
    }

    /**
     * 有条件分页查询
     *
     * @param pageIndex
     * @param pageSize
     * @param orderInfoDto
     * @return
     */
    @Override
    @Cacheable(key = "#root.methodName+'_'+#pageIndex+'_'+#orderInfoDto.toString()", unless = "#result.list.size() == 0")
    public PageInfo<RaOrder> findOrderByPropertyWithPage(int pageIndex, int pageSize, OrderInfoDto orderInfoDto) {
        PageHelper.startPage(pageIndex, pageSize);
        lock.lock();
        try {
            List<RaOrder> raOrderList = raOrderDao.findByProperty(orderInfoDto);
            raOrderList.forEach(raOrder -> {
                Map<String, Object> map = new HashMap<>();
                map.put("label", label);
                map.put("type", raOrder.getStatus());
                String status = raStatusInfoService.findOneStatus(map);
                raOrder.setStatusStr(status);
                RaHourseInfo raHourseInfo = raHouseInfoService.findHouseInfoById(raOrder.getHourseId());
                if (raHourseInfo != null)
                    raOrder.setCloudId(raHourseInfo.getCloudId());
            });
            PageInfo<RaOrder> pageInfo = new PageInfo<>(raOrderList);
            return pageInfo;
        } catch (Exception e) {
            log.error("RaOrderService异常:", e);
            e.printStackTrace();
            return new PageInfo<>(Collections.emptyList());
        } finally {
            lock.unlock();
        }
    }

    @Override
    @Cacheable(key = "#root.methodName+'_'+#pageIndex+'_'+#orderInfoDto.toString()", unless = "#result.list.size() == 0")
    public PageInfo<RaOrder> frontFindByPropertyWithPage(int pageIndex, int pageSize, OrderInfoDto orderInfoDto) {
        PageHelper.startPage(pageIndex, pageSize);
        lock.lock();
        try {
            List<RaOrder> raOrderList = raOrderDao.frontFindByProperty(orderInfoDto);
            raOrderList.forEach(raOrder -> {
                Map<String, Object> map = new HashMap<>();
                map.put("label", label);
                map.put("type", raOrder.getStatus());
                String status = raStatusInfoService.findOneStatus(map);
                raOrder.setStatusStr(status);
                RaHourseInfo raHourseInfo = raHouseInfoService.findHouseInfoById(raOrder.getHourseId());
                if (raHourseInfo != null)
                    raOrder.setCloudId(raHourseInfo.getCloudId());
            });
            PageInfo<RaOrder> pageInfo = new PageInfo<>(raOrderList);
            return pageInfo;
        } catch (Exception e) {
            log.error("RaOrderService异常:", e);
            e.printStackTrace();
            return new PageInfo<>(Collections.emptyList());
        } finally {
            lock.unlock();
        }
    }

    /**
     * 根据id无分页查询
     *
     * @param id
     * @return
     */
    @Override
    @Cacheable(key = "#root.methodName+'_'+#id", unless = "#result == null")
    public RaOrder findOrderById(String id) {
        try {
            RaOrder raOrder = raOrderDao.findOrderById(id);
            RaHourseInfo raHourseInfo = raHouseInfoService.findHouseInfoById(raOrder.getHourseId());
            if (raHourseInfo != null)
                raOrder.setCloudId(raHourseInfo.getCloudId());
            return raOrder;
        } catch (Exception e) {
            log.error("RaOrderService异常:", e);
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 根据landlordId无分页查询
     *
     * @param landlordId
     * @return
     */
    @Override
    @Cacheable(key = "#root.methodName+'_'+#landlordId", unless = "#result.size() == 0")
    public List<RaOrder> findOrderByLandlordId(String landlordId) {
        try {
            List<RaOrder> raOrderList = raOrderDao.findOrderByLandlordId(landlordId);
            raOrderList.forEach(raOrder -> {
                Map<String, Object> map = new HashMap<>();
                map.put("label", label);
                map.put("type", raOrder.getStatus());
                String status = raStatusInfoService.findOneStatus(map);
                raOrder.setStatusStr(status);
                RaHourseInfo raHourseInfo = raHouseInfoService.findHouseInfoById(raOrder.getHourseId());
                if (raHourseInfo != null)
                    raOrder.setCloudId(raHourseInfo.getCloudId());
            });
            return raOrderList;
        } catch (Exception e) {
            log.error("RaOrderService异常:", e);
            e.printStackTrace();
            return Collections.EMPTY_LIST;
        }
    }

    /**
     * 根据tenantId无分页查询
     *
     * @param tenantId
     * @return
     */
    @Override
    @Cacheable(key = "#root.methodName+'_'+#tenantId", unless = "#result.size() == 0")
    public List<RaOrder> findOrderByTenantId(String tenantId) {
        try {
            List<RaOrder> raOrderList = raOrderDao.findOrderByTenantId(tenantId);
            raOrderList.forEach(raOrder -> {
                Map<String, Object> map = new HashMap<>();
                map.put("label", label);
                map.put("type", raOrder.getStatus());
                String status = raStatusInfoService.findOneStatus(map);
                raOrder.setStatusStr(status);
                RaHourseInfo raHourseInfo = raHouseInfoService.findHouseInfoById(raOrder.getHourseId());
                if (raHourseInfo != null)
                    raOrder.setCloudId(raHourseInfo.getCloudId());
            });
            return raOrderList;
        } catch (Exception e) {
            log.error("RaOrderService异常:", e);
            e.printStackTrace();
            return Collections.EMPTY_LIST;
        }
    }

    @Override
    @Cacheable(key = "#root.methodName+'_'+#status", unless = "#result.size() == 0")
    public List<RaOrder> findOrderByStatus(int status) {
        try {
            List<RaOrder> raOrderList = raOrderDao.findOrderByStatus(status);
            Map<String, Object> map = new HashMap<>();
            map.put("label", label);
            map.put("type", status);
            raOrderList.forEach(raOrder -> {
                String statusStr = raStatusInfoService.findOneStatus(map);
                raOrder.setStatusStr(statusStr);
                RaHourseInfo raHourseInfo = raHouseInfoService.findHouseInfoById(raOrder.getHourseId());
                if (raHourseInfo != null)
                    raOrder.setCloudId(raHourseInfo.getCloudId());
            });
            return raOrderList;
        } catch (Exception e) {
            log.error("RaOrderService异常:", e);
            e.printStackTrace();
            return Collections.EMPTY_LIST;
        }
    }

    /**
     * 根据landlordId分页查询
     *
     * @param pageIndex
     * @param pageSize
     * @param landlordId
     * @return
     */
    @Override
    @Cacheable(key = "#root.methodName+'_'+#landlordId+'_'+#pageIndex", unless = "#result.list.size() == 0")
    public PageInfo<RaOrder> findOrderByLandlordIdWithPage(int pageIndex, int pageSize, String landlordId) {
        PageHelper.startPage(pageIndex, pageSize);
        lock.lock();
        try {
            List<RaOrder> raOrderList = raOrderDao.findOrderByLandlordId(landlordId);
            raOrderList.forEach(raOrder -> {
                Map<String, Object> map = new HashMap<>();
                map.put("label", label);
                map.put("type", raOrder.getStatus());
                String status = raStatusInfoService.findOneStatus(map);
                raOrder.setStatusStr(status);
                RaHourseInfo raHourseInfo = raHouseInfoService.findHouseInfoById(raOrder.getHourseId());
                if (raHourseInfo != null)
                    raOrder.setCloudId(raHourseInfo.getCloudId());
            });
            PageInfo<RaOrder> pageInfo = new PageInfo<>(raOrderList);
            return pageInfo;
        } catch (Exception e) {
            log.error("RaOrderService异常:", e);
            e.printStackTrace();
            return new PageInfo<>(Collections.emptyList());
        } finally {
            lock.unlock();
        }
    }

    /**
     * 根据tenantId分页查询
     *
     * @param pageIndex
     * @param pageSize
     * @param tenantId
     * @return
     */
    @Override
    @Cacheable(key = "#root.methodName+'_'+#tenantId+'_'+#pageIndex", unless = "#result.list.size() == 0")
    public PageInfo<RaOrder> findOrderByTenantIdWithPage(int pageIndex, int pageSize, String tenantId) {
        PageHelper.startPage(pageIndex, pageSize);
        lock.lock();
        try {
            List<RaOrder> raOrderList = raOrderDao.findOrderByTenantId(tenantId);
            raOrderList.forEach(raOrder -> {
                Map<String, Object> map = new HashMap<>();
                map.put("label", label);
                map.put("type", raOrder.getStatus());
                String status = raStatusInfoService.findOneStatus(map);
                raOrder.setStatusStr(status);
                RaHourseInfo raHourseInfo = raHouseInfoService.findHouseInfoById(raOrder.getHourseId());
                if (raHourseInfo != null)
                    raOrder.setCloudId(raHourseInfo.getCloudId());
            });
            PageInfo<RaOrder> pageInfo = new PageInfo<>(raOrderList);
            return pageInfo;
        } catch (Exception e) {
            log.error("RaOrderService异常:", e);
            e.printStackTrace();
            return new PageInfo<>(Collections.emptyList());
        } finally {
            lock.unlock();
        }
    }

    @Override
    @Cacheable(key = "#root.methodName+'_'+#status+'_'+#pageIndex", unless = "#result.list.size() == 0")
    public PageInfo<RaOrder> findOrderByStatusWithPage(int pageIndex, int pageSize, int status) {
        PageHelper.startPage(pageIndex, pageSize);
        lock.lock();
        try {
            List<RaOrder> raOrderList = raOrderDao.findOrderByStatus(status);
            Map<String, Object> map = new HashMap<>();
            map.put("label", label);
            map.put("type", status);
            raOrderList.forEach(raOrder -> {
                String statusStr = raStatusInfoService.findOneStatus(map);
                raOrder.setStatusStr(statusStr);
                RaHourseInfo raHourseInfo = raHouseInfoService.findHouseInfoById(raOrder.getHourseId());
                if (raHourseInfo != null)
                    raOrder.setCloudId(raHourseInfo.getCloudId());
            });
            PageInfo<RaOrder> pageInfo = new PageInfo<>(raOrderList);
            return pageInfo;
        } catch (Exception e) {
            log.error("RaOrderService异常:", e);
            e.printStackTrace();
            return new PageInfo<>(Collections.emptyList());
        } finally {
            lock.unlock();
        }
    }

    /**
     * 添加
     *
     * @param raOrder
     * @return
     */
    @Override
    @CacheEvict(allEntries = true)
    @Transactional(isolation = Isolation.READ_COMMITTED)
    public int addOneOrder(RaOrder raOrder) {
        try {
            raOrder.setId(UUID.randomUUID().toString().replaceAll("-", ""));
            raOrder.setCreateTime(new DateTime().toString("yyyy-MM-dd HH:mm:ss"));
            return raOrderDao.addOneOrder(raOrder);
        } catch (Exception e) {
            log.error("RaOrderService异常:", e);
            e.printStackTrace();
            return 0;
        }
    }

    @Override
    @Async("orderInfoTaskAsyncPool")
    @CacheEvict(allEntries = true)
    @Transactional(isolation = Isolation.READ_COMMITTED)
    public Future<Boolean> addOneOrderSync(RaOrder raOrder) {
        Future<Boolean> future;
        try {
            raOrder.setId(UUID.randomUUID().toString().replaceAll("-", ""));
            raOrder.setCreateTime(new DateTime().toString("yyyy-MM-dd HH:mm:ss"));
            raOrderDao.addOneOrder(raOrder);
            future = new AsyncResult<>(true);
        } catch (Exception e) {
            log.error("RaOrderService异常:", e);
            e.printStackTrace();
            future = new AsyncResult<>(false);
        }
        return future;
    }

    /**
     * 修改部分属性
     *
     * @param orderInfoDto
     * @return
     */
    @Override
    @CacheEvict(allEntries = true)
    @Transactional(isolation = Isolation.READ_COMMITTED)
    public int updateProperty(OrderInfoDto orderInfoDto) {
        try {
            return raOrderDao.updateProperty(orderInfoDto);
        } catch (Exception e) {
            log.error("RaOrderService异常:", e);
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * 修改订单详情
     *
     * @param id
     * @param orderDetailEntity
     * @return
     */
    @Override
    @CacheEvict(allEntries = true)
    @Transactional(isolation = Isolation.READ_COMMITTED)
    public int updateDetail(String id, OrderDetailEntity orderDetailEntity) {
        try {
            Map<String, Object> map = new HashMap<>();
            map.put("id", id);
            map.put("detail", JSON.toJSONString(orderDetailEntity));
            return raOrderDao.updateDetail(map);
        } catch (Exception e) {
            log.error("RaOrderService异常:", e);
            e.printStackTrace();
            return 0;
        }
    }

    @Override
    @Async("orderInfoTaskAsyncPool")
    @CacheEvict(allEntries = true)
    @Transactional(isolation = Isolation.READ_COMMITTED)
    public Future<Boolean> updateDetailSync(String id, OrderDetailEntity orderDetailEntity) {
        Future<Boolean> future;
        try {
            Map<String, Object> map = new HashMap<>();
            map.put("id", id);
            map.put("detail", JSON.toJSONString(orderDetailEntity));
            raOrderDao.updateDetail(map);
            future = new AsyncResult<>(true);
        } catch (Exception e) {
            log.error("RaOrderService异常:", e);
            e.printStackTrace();
            future = new AsyncResult<>(false);
        }
        return future;
    }

    /**
     * 删除订单
     *
     * @param list
     * @return
     */
    @Override
    @CacheEvict(allEntries = true)
    @Transactional(isolation = Isolation.READ_COMMITTED)
    public int deleteByIds(List<String> list) {
        try {
            return raOrderDao.deleteByIds(list);
        } catch (Exception e) {
            log.error("RaOrderService异常:", e);
            e.printStackTrace();
            return 0;
        }
    }

    @Override
    @CacheEvict(allEntries = true)
    @Transactional(isolation = Isolation.READ_COMMITTED)
    @Async("orderInfoTaskAsyncPool")
    public Future<Boolean> updateDelflag(List<String> list) {
        Future<Boolean> future;
        try {
            raOrderDao.updateDelflag(list);
            future = new AsyncResult<>(true);
        } catch (Exception e) {
            log.error("RaOrderService异常:", e);
            e.printStackTrace();
            future = new AsyncResult<>(false);
        }
        return future;
    }

    public List<String> parseListId(List<RaOrder> raOrderList) {
        return raOrderList.stream().map(RaOrder::getId).collect(Collectors.toList());
    }
}
